Skip to contentMethod: transactionStarted(EntityTransaction, AbstractEntityManager)
1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jopa.sessions;
19:
20: import cz.cvut.kbss.jopa.accessors.DefaultStorageAccessor;
21: import cz.cvut.kbss.jopa.accessors.StorageAccessor;
22: import cz.cvut.kbss.jopa.model.AbstractEntityManager;
23: import cz.cvut.kbss.jopa.sessions.cache.CacheManager;
24: import cz.cvut.kbss.jopa.model.MetamodelImpl;
25: import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
26: import cz.cvut.kbss.jopa.model.query.criteria.CriteriaBuilder;
27: import cz.cvut.kbss.jopa.query.criteria.CriteriaBuilderImpl;
28: import cz.cvut.kbss.jopa.sessions.cache.CacheFactory;
29: import cz.cvut.kbss.jopa.transactions.EntityTransaction;
30: import cz.cvut.kbss.jopa.utils.ChangeTrackingMode;
31: import cz.cvut.kbss.jopa.utils.Configuration;
32: import cz.cvut.kbss.jopa.utils.Wrapper;
33: import cz.cvut.kbss.ontodriver.OntologyStorageProperties;
34: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
35: import org.slf4j.Logger;
36: import org.slf4j.LoggerFactory;
37:
38: import java.util.Map;
39: import java.util.Objects;
40: import java.util.concurrent.ConcurrentHashMap;
41:
42: /**
43: * The ServerSession is the primary interface for accessing the ontology.
44: * <p>
45: * It manages an accessor object, which performs the queries.
46: */
47: public class ServerSession extends AbstractSession implements Wrapper {
48:
49: private static final Logger LOG = LoggerFactory.getLogger(ServerSession.class);
50:
51: private final MetamodelImpl metamodel;
52:
53: private CacheManager liveObjectCache;
54: private StorageAccessor storageAccessor;
55: private final CriteriaBuilder criteriaBuilder;
56:
57: private Map<EntityTransaction, AbstractEntityManager> runningTransactions;
58:
59: ServerSession(MetamodelImpl metamodel) {
60: super(new Configuration());
61: this.metamodel = metamodel;
62: this.criteriaBuilder = new CriteriaBuilderImpl(metamodel);
63: }
64:
65: public ServerSession(OntologyStorageProperties storageProperties, Configuration configuration,
66: MetamodelImpl metamodel) {
67: super(configuration);
68: this.metamodel = metamodel;
69: this.criteriaBuilder = new CriteriaBuilderImpl(metamodel);
70: initialize(storageProperties, configuration, metamodel);
71: }
72:
73: /**
74: * Initializes this ServerSession. This in particular means initialization of the ontology accessor and live object
75: * cache.
76: *
77: * @param storageProperties Storage properties
78: * @param configuration Session configuration
79: * @param metamodel Metamodel of the managed classes and their attributes.
80: */
81: private void initialize(OntologyStorageProperties storageProperties, Configuration configuration,
82: Metamodel metamodel) {
83: assert configuration != null;
84: assert metamodel != null;
85: this.runningTransactions = new ConcurrentHashMap<>();
86: this.liveObjectCache = CacheFactory.createCache(configuration.getProperties());
87: liveObjectCache.setInferredClasses(metamodel.getInferredClasses());
88: this.storageAccessor = new DefaultStorageAccessor(storageProperties, configuration.getProperties());
89: }
90:
91: /**
92: * Acquires a {@link UnitOfWork} instance to perform transactional operations.
93: *
94: * @return UnitOfWork instance
95: */
96: public UnitOfWork acquireUnitOfWork(Configuration configuration) {
97: final ChangeTrackingMode mode = ChangeTrackingMode.resolve(configuration);
98: return switch (mode) {
99: case IMMEDIATE -> {
100: LOG.trace("Acquiring change tracking UnitOfWork.");
101: yield new ChangeTrackingUnitOfWork(this, configuration);
102: }
103: case ON_COMMIT -> {
104: LOG.trace("Acquiring on commit change calculating UnitOfWork.");
105: yield new OnCommitChangePropagatingUnitOfWork(this, configuration);
106: }
107: };
108: }
109:
110: @Override
111: protected ConnectionWrapper acquireConnection() {
112: return new ConnectionWrapper(storageAccessor.acquireConnection());
113: }
114:
115: @Override
116: public CacheManager getLiveObjectCache() {
117: return liveObjectCache;
118: }
119:
120: public void transactionStarted(EntityTransaction t, AbstractEntityManager em) {
121:• assert t.isActive();
122: runningTransactions.put(t, em);
123: }
124:
125: public void transactionFinished(EntityTransaction t) {
126: if (t == null) {
127: return;
128: }
129: runningTransactions.remove(t);
130: }
131:
132: /**
133: * Close the server session and all connections to the underlying data source.
134: */
135: public void close() {
136: if (!runningTransactions.isEmpty()) {
137: LOG.warn("There are still transactions running. Marking them for rollback.");
138: runningTransactions.keySet().stream().filter(EntityTransaction::isActive)
139: .forEach(EntityTransaction::setRollbackOnly);
140: }
141: if (storageAccessor != null && storageAccessor.isOpen()) {
142: try {
143: storageAccessor.close();
144: } catch (OntoDriverException e) {
145: LOG.error("Exception caught when closing the storage accessor.", e);
146: }
147: }
148: liveObjectCache.close();
149: }
150:
151: @Override
152: public MetamodelImpl getMetamodel() {
153: return metamodel;
154: }
155:
156: @Override
157: public boolean isEntityType(Class<?> cls) {
158: return metamodel.isEntityType(cls);
159: }
160:
161: @Override
162: public CriteriaBuilder getCriteriaBuilder() {
163: return criteriaBuilder;
164: }
165:
166: @Override
167: public <T> T unwrap(Class<T> cls) {
168: Objects.requireNonNull(cls);
169: if (cls.isAssignableFrom(getClass())) {
170: return cls.cast(this);
171: } else if (cls.isAssignableFrom(liveObjectCache.getClass())) {
172: return cls.cast(liveObjectCache);
173: }
174: return storageAccessor.unwrap(cls);
175: }
176: }